domain (only if the caller is sufficiently privileged).
Signed-off-by: Keir Fraser <keir@xensource.com>
static int setup_blkring(struct xenbus_device *dev, struct blkfront_info *info)
{
blkif_sring_t *sring;
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ evtchn_op_t op;
int err;
info->ring_ref = GRANT_INVALID_REF;
}
info->ring_ref = err;
- op.u.alloc_unbound.dom = info->backend_id;
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
gnttab_end_foreign_access(info->ring_ref, 0);
xenbus_dev_error(dev, err, "allocating event channel");
return err;
}
+
blkif_connect(info, op.u.alloc_unbound.port);
+
return 0;
}
static int setup_device(struct xenbus_device *dev, struct netfront_info *info)
{
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ evtchn_op_t op;
int err;
info->tx_ring_ref = GRANT_INVALID_REF;
}
info->rx_ring_ref = err;
- op.u.alloc_unbound.dom = info->backend_id;
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
xenbus_dev_error(dev, err, "allocating event channel");
goto out;
}
+
connect_device(info, op.u.alloc_unbound.port);
+
return 0;
out:
{
tpmif_tx_interface_t *sring;
struct tpm_private *tp = &my_private;
-
- evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
+ evtchn_op_t op;
int err;
sring = (void *)__get_free_page(GFP_KERNEL);
}
info->ring_ref = err;
- op.u.alloc_unbound.dom = backend_id;
+ op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.dom = DOMID_SELF;
+ op.u.alloc_unbound.remote_dom = backend_id;
err = HYPERVISOR_event_channel_op(&op);
if (err) {
gnttab_end_foreign_access(info->ring_ref, 0);
xenbus_dev_error(dev, err, "allocating event channel");
return err;
}
+
tpmif_connect(op.u.alloc_unbound.port, backend_id);
+
return 0;
}
int xc_evtchn_alloc_unbound(int xc_handle,
+ u32 remote_dom,
u32 dom,
int *port)
{
int rc;
op.cmd = EVTCHNOP_alloc_unbound;
+ op.u.alloc_unbound.remote_dom = (domid_t)remote_dom;
op.u.alloc_unbound.dom = (domid_t)dom;
op.u.alloc_unbound.port = (port != NULL) ? *port : 0;
* well-known port within a domain to receive events on.
*
* @parm xc_handle a handle to an open hypervisor interface
- * @parm dom the ID of the domain. This maybe DOMID_SELF
+ * @parm remote_dom the ID of the domain who will later bind
+ * @parm dom the ID of the local domain (the 'allocatee')
* @parm port a pointer to a port. This is an in/out parameter. If *port is
* 0, then a new port will be assigned, if port is > 0 then that
* port is allocated if the port is unallocated.
* @return 0 on success, -1 on failure
*/
int xc_evtchn_alloc_unbound(int xc_handle,
+ u32 remote_dom,
u32 dom,
int *port);
{
XcObject *xc = (XcObject *)self;
- u32 dom;
+ u32 dom = DOMID_SELF, remote_dom;
int port = 0;
- static char *kwd_list[] = { "dom", "port", NULL };
+ static char *kwd_list[] = { "remote_dom", "dom", "port", NULL };
- if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwd_list,
- &dom, &port) )
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list,
+ &remote_dom, &dom, &port) )
return NULL;
- if ( xc_evtchn_alloc_unbound(xc->xc_handle, dom, &port) != 0 )
+ if ( xc_evtchn_alloc_unbound(xc->xc_handle, remote_dom, dom, &port) != 0 )
return PyErr_SetFromErrno(xc_error);
return PyInt_FromLong(port);
static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
{
struct evtchn *chn;
- struct domain *d = current->domain;
+ struct domain *d;
int port = alloc->port;
+ domid_t dom = alloc->dom;
long rc = 0;
+ if ( dom == DOMID_SELF )
+ dom = current->domain->domain_id;
+ else if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+
+ if ( (d = find_domain_by_id(dom)) == NULL )
+ return -ESRCH;
+
spin_lock(&d->evtchn_lock);
/* Obtain, or ensure that we already have, a valid <port>. */
{
case ECS_FREE:
chn->state = ECS_UNBOUND;
- chn->u.unbound.remote_domid = alloc->dom;
+ chn->u.unbound.remote_domid = alloc->remote_dom;
break;
case ECS_UNBOUND:
- if ( chn->u.unbound.remote_domid != alloc->dom )
+ if ( chn->u.unbound.remote_domid != alloc->remote_dom )
ERROR_EXIT(-EINVAL);
break;
out:
spin_unlock(&d->evtchn_lock);
+ put_domain(d);
+
alloc->port = port;
+
return rc;
}
#define __XEN_PUBLIC_EVENT_CHANNEL_H__
/*
- * EVTCHNOP_alloc_unbound: Prepare a local port for binding to <dom>.
- * <port> may be wildcarded by setting to zero, in which case a fresh port
- * will be allocated, and the field filled in on return.
+ * EVTCHNOP_alloc_unbound: Allocate a port in <dom> for later binding to
+ * <remote_dom>. <port> may be wildcarded by setting to zero, in which case a
+ * fresh port will be allocated, and the field filled in on return.
+ * NOTES:
+ * 1. If the caller is unprivileged then <dom> must be DOMID_SELF.
*/
#define EVTCHNOP_alloc_unbound 6
typedef struct evtchn_alloc_unbound {
/* IN parameters */
- domid_t dom;
+ domid_t dom, remote_dom;
/* IN/OUT parameters */
u32 port;
} evtchn_alloc_unbound_t;